/*
 * Factory.cpp
 *
 *  Created on: 10 nov. 2011
 *  Authors: bnoleau, cybourdi, rlecrois
 */

#include "Factory.h"

Factory *Factory::uniqueFactory = NULL;

Factory::Factory() {
	

}

Factory::~Factory() {
	
}

Factory* Factory::getInstance() {
    if(uniqueFactory == NULL)
        uniqueFactory = new Factory();

    return uniqueFactory;
}

Graph* Factory::createGraph(int n, double p) {

	Graph* g = new Graph(n);

	for (int i = 0; i < n; i++) {
		for (int j = i+1; j < n; j++) {
			if (randEdge(p)) {
				Node* n1 = g->nodeAt(i);
				Node* n2 = g->nodeAt(j);
				g->createEdge(n1, n2);
			}
		}
	}
	return g;

}

Graph* Factory::createGraphWithoutEdge(int n) {
	return new Graph(n);
}

Graph* Factory::createEmptyGraph() {
	return createGraphWithoutEdge(0);
}

Graph* Factory::createTree(int n, int nbMinChild, int nbMaxChild) {

	Graph* tree = new Graph(n);

	int nbNodesCreated = 1;
	int cursor = 0;

	while (nbNodesCreated < (n)) {
		Node* currentNode = tree->nodeAt(cursor);
		int maxRand;

		if (nbMaxChild > (n - (nbNodesCreated - 1)))
			maxRand = (n - (nbNodesCreated - 1));
		else
			maxRand = nbMaxChild;
		int nbChildren = rand() % (maxRand - nbMinChild) + nbMinChild;

		if (nbChildren > 0) {
			for (int i = 0; i < nbChildren; i++) {
				Node* n2 = tree->nodeAt(nbNodesCreated);
				tree->createEdge(currentNode, n2);
				nbNodesCreated++;
			}
			cursor++;
		}
	}
	return tree;
}

Graph* Factory::createBinaryTree(int n) {
	return createTree(n, 0, 3);

}

Graph* Factory::createBipartiteGraph(int n, double p) {
	int sizeFirstSet = rand() % (n - 1) + 1;

	return createMinCoverGraph(n, sizeFirstSet, p);
}

Graph* Factory::createEmptyTree() {
	return createGraphWithoutEdge(0);
}

Graph* Factory::createTreeWithoutEdge(int n) {
	return new Graph(n);
}

Graph* Factory::createMinCoverGraph(int n, int k, double p) {

	Graph* minCoverGraph = new Graph(n);

	int sizeFirstSet = k;

	for (int i = 0; i < sizeFirstSet; i++) {
		for (int j = sizeFirstSet; j < n; j++) {
			if (randEdge(p)) {
				Node* n1 = minCoverGraph->nodeAt(i);
				Node* n2 = minCoverGraph->nodeAt(j);
				minCoverGraph->createEdge(n1, n2);
			}
		}
	}
	return minCoverGraph;
}

bool Factory::randEdge(double p) {
	if (p == 1)
		return true;
	else
		return ((rand() / (double) RAND_MAX) < p);
}
